package com.stars.easyms.proxy;

import com.stars.easyms.proxy.exception.EasyMsProxyException;
import lombok.Setter;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.cglib.core.SpringNamingPolicy;
import org.springframework.cglib.proxy.Enhancer;

import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.Objects;

/**
 * <p>className: EasyMsProxyServiceFactoryBean</p>
 * <p>description: EasyMsProxyService工厂Bean</p>
 *
 * @author guoguifang
 * @version 1.7.3
 * @date 2021/3/24 2:34 下午
 */
@Setter
class EasyMsProxyServiceFactoryBean implements FactoryBean<Object> {

    private Class<?> type;

    private String target;

    private String url;

    private String path;

    @Override
    public Object getObject() throws Exception {
        if (Modifier.isFinal(type.getModifiers())) {
            throw new EasyMsProxyException("The class '{}' with @EasyMsProxyService annotation cannot be final!", type.getName());
        }

        if (type.isInterface()) {
            return Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, new EasyMsProxyJdkMethodInterceptor(type));
        }

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(type);
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setCallback(new EasyMsProxyCglibMethodInterceptor());
        return enhancer.create();
    }

    @Override
    public Class<?> getObjectType() {
        return type;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        EasyMsProxyServiceFactoryBean that = (EasyMsProxyServiceFactoryBean) o;
        return Objects.equals(target, that.target)
                && Objects.equals(path, that.path)
                && Objects.equals(type, that.type)
                && Objects.equals(url, that.url);
    }

    @Override
    public int hashCode() {
        return Objects.hash(target, path, type, url);
    }

    @Override
    public String toString() {
        return new StringBuilder("EasyMsProxyServiceFactoryBean{")
                .append("type=").append(type).append(", ")
                .append("target='").append(target).append("', ")
                .append("url='").append(url).append("', ")
                .append("path='").append(path).append("}")
                .toString();
    }

}
